/*
 * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __BATTLEGROUNDAB_H
#define __BATTLEGROUNDAB_H

class Battleground;

enum BG_AB_WorldStates
{
    BG_AB_OP_OCCUPIED_BASES_HORDE        = 1778,
    BG_AB_OP_OCCUPIED_BASES_ALLY         = 1779,
    BG_AB_OP_RESOURCES_ALLY              = 1776,
    BG_AB_OP_RESOURCES_HORDE             = 1777,
    BG_AB_OP_RESOURCES_MAX               = 1780,
    BG_AB_OP_RESOURCES_WARNING           = 1955

/*
    BG_AB_OP_STABLE_ICON                 = 1842,             // Stable map icon (NONE).
    BG_AB_OP_STABLE_STATE_ALIENCE        = 1767,             // Stable map state (ALIENCE).
    BG_AB_OP_STABLE_STATE_HORDE          = 1768,             // Stable map state (HORDE).
    BG_AB_OP_STABLE_STATE_CON_ALI        = 1769,             // Stable map state (CON ALIENCE).
    BG_AB_OP_STABLE_STATE_CON_HOR        = 1770,             // Stable map state (CON HORDE).

    BG_AB_OP_FARM_ICON                   = 1845,             // Farm map icon (NONE).
    BG_AB_OP_FARM_STATE_ALIENCE          = 1772,             // Farm state (ALIENCE).
    BG_AB_OP_FARM_STATE_HORDE            = 1773,             // Farm state (HORDE).
    BG_AB_OP_FARM_STATE_CON_ALI          = 1774,             // Farm state (CON ALIENCE).
    BG_AB_OP_FARM_STATE_CON_HOR          = 1775,             // Farm state (CON HORDE).

    BG_AB_OP_BLACKSMITH_ICON             = 1846,             // Blacksmith map icon (NONE).
    BG_AB_OP_BLACKSMITH_STATE_ALIENCE    = 1782,             // Blacksmith map state (ALIENCE).
    BG_AB_OP_BLACKSMITH_STATE_HORDE      = 1783,             // Blacksmith map state (HORDE).
    BG_AB_OP_BLACKSMITH_STATE_CON_ALI    = 1784,             // Blacksmith map state (CON ALIENCE).
    BG_AB_OP_BLACKSMITH_STATE_CON_HOR    = 1785,             // Blacksmith map state (CON HORDE).

    BG_AB_OP_LUMBERMILL_ICON             = 1844,             // Lumber Mill map icon (NONE).
    BG_AB_OP_LUMBERMILL_STATE_ALIENCE    = 1792,             // Lumber Mill map state (ALIENCE).
    BG_AB_OP_LUMBERMILL_STATE_HORDE      = 1793,             // Lumber Mill map state (HORDE).
    BG_AB_OP_LUMBERMILL_STATE_CON_ALI    = 1794,             // Lumber Mill map state (CON ALIENCE).
    BG_AB_OP_LUMBERMILL_STATE_CON_HOR    = 1795,             // Lumber Mill map state (CON HORDE).

    BG_AB_OP_GOLDMINE_ICON               = 1843,             // Gold Mine map icon (NONE).
    BG_AB_OP_GOLDMINE_STATE_ALIENCE      = 1787,             // Gold Mine map state (ALIENCE).
    BG_AB_OP_GOLDMINE_STATE_HORDE        = 1788,             // Gold Mine map state (HORDE).
    BG_AB_OP_GOLDMINE_STATE_CON_ALI      = 1789,             // Gold Mine map state (CON ALIENCE).
    BG_AB_OP_GOLDMINE_STATE_CON_HOR      = 1790              // Gold Mine map state (CON HORDE).
*/
};

const uint32 BG_AB_OP_NODESTATES[5]      =    {1767, 1782, 1772, 1792, 1787};
const uint32 BG_AB_OP_NODEICONS[5]       =    {1842, 1846, 1845, 1844, 1843};

enum BG_AB_NodeObjectId
{
    BG_AB_OBJECTID_NODE_BANNER_0         = 180087,       // Stables banner
    BG_AB_OBJECTID_NODE_BANNER_1         = 180088,       // Blacksmith banner
    BG_AB_OBJECTID_NODE_BANNER_2         = 180089,       // Farm banner
    BG_AB_OBJECTID_NODE_BANNER_3         = 180090,       // Lumber mill banner
    BG_AB_OBJECTID_NODE_BANNER_4         = 180091        // Gold mine banner
};

enum BG_AB_ObjectType
{
    // Banners (Note: For all 5 node points; 8 * 5 = 40 objects).
    BG_AB_OBJECT_BANNER_NEUTRAL          = 0,
    BG_AB_OBJECT_BANNER_CONT_A           = 1,
    BG_AB_OBJECT_BANNER_CONT_H           = 2,
    BG_AB_OBJECT_BANNER_ALLY             = 3,
    BG_AB_OBJECT_BANNER_HORDE            = 4,

    // Auras.
    BG_AB_OBJECT_AURA_ALLY               = 5,
    BG_AB_OBJECT_AURA_HORDE              = 6,
    BG_AB_OBJECT_AURA_CONTESTED          = 7,

    // Gates.
    BG_AB_OBJECT_GATE_A                  = 40,
    BG_AB_OBJECT_GATE_H                  = 41,

    // Buffs.
    BG_AB_OBJECT_SPEEDBUFF_STABLES       = 42,
    BG_AB_OBJECT_REGENBUFF_STABLES       = 43,
    BG_AB_OBJECT_BERSERKBUFF_STABLES     = 44,
    BG_AB_OBJECT_SPEEDBUFF_BLACKSMITH    = 45,
    BG_AB_OBJECT_REGENBUFF_BLACKSMITH    = 46,
    BG_AB_OBJECT_BERSERKBUFF_BLACKSMITH  = 47,
    BG_AB_OBJECT_SPEEDBUFF_FARM          = 48,
    BG_AB_OBJECT_REGENBUFF_FARM          = 49,
    BG_AB_OBJECT_BERSERKBUFF_FARM        = 50,
    BG_AB_OBJECT_SPEEDBUFF_LUMBER_MILL   = 51,
    BG_AB_OBJECT_REGENBUFF_LUMBER_MILL   = 52,
    BG_AB_OBJECT_BERSERKBUFF_LUMBER_MILL = 53,
    BG_AB_OBJECT_SPEEDBUFF_GOLD_MINE     = 54,
    BG_AB_OBJECT_REGENBUFF_GOLD_MINE     = 55,
    BG_AB_OBJECT_BERSERKBUFF_GOLD_MINE   = 56,

    BG_AB_OBJECT_MAX                     = 57
};

/* Object id templates from DB */
enum BG_AB_ObjectTypes
{
    // Banners.
    BG_AB_OBJECTID_BANNER_A             = 180058,
    BG_AB_OBJECTID_BANNER_CONT_A        = 180059,
    BG_AB_OBJECTID_BANNER_H             = 180060,
    BG_AB_OBJECTID_BANNER_CONT_H        = 180061,

    // Auras.
    BG_AB_OBJECTID_AURA_A               = 180100,
    BG_AB_OBJECTID_AURA_H               = 180101,
    BG_AB_OBJECTID_AURA_C               = 180102,

    // Gates.
    BG_AB_OBJECTID_GATE_A               = 180255,
    BG_AB_OBJECTID_GATE_H               = 180256
};

enum BG_AB_Timers
{
    BG_AB_FLAG_CAPTURING_TIME           = 60000
};

enum BG_AB_Score
{
    BG_AB_WARNING_NEAR_VICTORY_SCORE    = 1400,
    BG_AB_MAX_TEAM_SCORE                = 1600
};

/* Do not change below, or this thing will go boom! */
enum BG_AB_BattlegroundNodes
{
    BG_AB_NODE_STABLES                  = 0,
    BG_AB_NODE_BLACKSMITH               = 1,
    BG_AB_NODE_FARM                     = 2,
    BG_AB_NODE_LUMBER_MILL              = 3,
    BG_AB_NODE_GOLD_MINE                = 4,

    BG_AB_DYNAMIC_NODES_COUNT           = 5, // Dynamic nodes that can be captured.

    BG_AB_SPIRIT_ALIANCE                = 5,
    BG_AB_SPIRIT_HORDE                  = 6,

    BG_AB_ALL_NODES_COUNT               = 7  // All nodes (dynamic and static).
};

enum BG_AB_NodeStatus
{
    BG_AB_NODE_TYPE_NEUTRAL             = 0,

    BG_AB_NODE_TYPE_CONTESTED           = 1,
    BG_AB_NODE_STATUS_ALLY_CONTESTED    = 1,
    BG_AB_NODE_STATUS_HORDE_CONTESTED   = 2,

    BG_AB_NODE_TYPE_OCCUPIED            = 3,
    BG_AB_NODE_STATUS_ALLY_OCCUPIED     = 3,
    BG_AB_NODE_STATUS_HORDE_OCCUPIED    = 4
};

enum BG_AB_Sounds
{
    BG_AB_SOUND_NODE_CLAIMED            = 8192,
    BG_AB_SOUND_NODE_CAPTURED_ALLIANCE  = 8173,
    BG_AB_SOUND_NODE_CAPTURED_HORDE     = 8213,
    BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE = 8212,
    BG_AB_SOUND_NODE_ASSAULTED_HORDE    = 8174,
    BG_AB_SOUND_NEAR_VICTORY            = 8456
};

enum BG_AB_Objectives
{
    AB_OBJECTIVE_ASSAULT_BASE           = 122,
    AB_OBJECTIVE_DEFEND_BASE            = 123
};

/* Holiday / Regular Honor / Rep gains */

// Stated as http://us.battle.net/wow/en/forum/topic/11914141511 MOP 5.4.7 changes.
#define BG_AB_NotABBGWeekendHonorTicks      130
#define BG_AB_ABBGWeekendHonorTicks         100

/*
    Patch 4.2.0 (2011-06-28): Reputation is now earned for every 260 resources (250 during Call to Arms).
    MOP updated : http://wow.gamepedia.com/Defilers / http://wow.gamepedia.com/League_of_Arathor quotes.

    Reputation is gained through participation in the Arathi Basin battleground. 
    When you fight in Arathi Basin you earn 16 reputation each 260 resources  (= 6 ticks per win).
    On Arathi Basin holiday weekends the required resources is reduced to 200 (= 8 ticks per win).
    Thus granting 96 rep per won Arathi Basin battle and 128 rep on holiday weekends.
*/
#define BG_AB_NotABBGWeekendReputationTicks 260
#define BG_AB_ABBGWeekendReputationTicks    200

#define AB_EVENT_START_BATTLE               9158 // Achievement: Let's Get This Done.

const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] =
{
    //        x,         y,          z,          o
    { 1166.785f, 1200.132f, -56.70859f, 0.9075713f },         // Stables.
    { 977.0156f, 1046.616f, -44.80923f, -2.600541f },         // Blacksmith.
    { 806.1821f, 874.2723f, -55.99371f, -2.303835f },         // Farm.
    { 856.1419f, 1148.902f,  11.18469f, -2.303835f },         // Lumber mill.
    { 1146.923f, 848.1782f, -110.917f, -0.7330382f }          // Gold mine.
};

const float BG_AB_DoorPositions[2][8] =
{
    //        x,         y,          z,          o,      rot0,       rot1,      rot2,       rot3
    { 1284.597f, 1281.167f, -15.97792f, 0.7068594f, 0.012957f, -0.060288f, 0.344959f,  0.936590f },
    { 708.0903f, 708.4479f, -17.8342f, -2.391099f,  0.050291f,  0.015127f, 0.929217f, -0.365784f }
};

// Tick intervals and given points: case 0, 1, 2, 3, 4, 5 captured nodes.
const uint32 BG_AB_TickIntervals[6] = { 0, 12000, 9000, 6000, 3000, 1000 };
const uint32 BG_AB_TickPoints[6]    = { 0,    10,   10,   10,   10,   30 };

// WorldSafeLocs ids for 5 nodes, and for ally, and horde starting location.
const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = { 895, 894, 893, 897, 896, 898, 899 };

const float BG_AB_BuffPositions[BG_AB_DYNAMIC_NODES_COUNT][4] =
{
    //       x,        y,       z,     o
    { 1185.71f, 1185.24f, -56.36f, 2.56f },                 // Stables.
    { 990.75f,  1008.18f, -42.60f, 2.43f },                 // Blacksmith.
    { 817.66f,   843.34f, -56.54f, 3.01f },                 // Farm.
    { 807.46f,  1189.16f,  11.92f, 5.44f },                 // Lumber mill.
    { 1146.62f,  816.94f, -98.49f, 6.14f }                  // Gold mine.
};

const float BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT][4] =
{
    //       x,        y,       z,     o
    { 1200.03f, 1171.09f, -56.47f, 5.15f },                 // Stables.
    { 1017.43f,  960.61f, -42.95f, 4.88f },                 // Blacksmith.
    {  833.00f,  793.00f, -57.25f, 5.27f },                 // Farm.
    {  775.17f, 1206.40f,  15.79f, 1.90f },                 // Lumber mill.
    { 1207.48f,  787.00f, -83.36f, 5.51f },                 // Gold mine.

    { 1354.05f, 1275.48f, -11.30f, 4.77f },                 // Alliance starting base.
    {  714.61f,  646.15f, -10.87f, 4.34f }                  // Horde starting base.
};

struct BG_AB_BannerTimer
{
    uint32      timer;
    uint8       type;
    uint8       teamIndex;
};

class BattlegroundABScore : public BattlegroundScore
{
    public:
        BattlegroundABScore(): BasesAssaulted(0), BasesDefended(0) { };

        virtual ~BattlegroundABScore() { };

        uint32 BasesAssaulted;
        uint32 BasesDefended;
};

class BattlegroundAB : public Battleground
{
    public:
         BattlegroundAB();
        ~BattlegroundAB();

        /* Inherited from Battleground class. */

        void Reset();
        bool SetupBattleground();
        void EndBattleground(uint32 winner);

        /* Players. */
        void AddPlayer(Player* player);
        void RemovePlayer(Player* player, uint64 guid, uint32 team);

        /* Doors. */
        void StartingEventCloseDoors();
        void StartingEventOpenDoors();

        /* WorldStates. */
        void FillInitialWorldStates(ByteBuffer &data);

        /* Areatriggers. */
        void HandleAreaTrigger(Player* Source, uint32 Trigger);

        /* Graveyards. */
        WorldSafeLocsEntry const* GetClosestGraveYard(Player* player);

        /* ScoreKeeping. */
        void UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor = true);

        /* Nodes occupying. */
        void EventPlayerClickedOnFlag(Player* source, GameObject* target_obj);

        /* Achievement requirements. */
        bool IsAllNodesControlledByTeam(uint32 team) const;  // overwrited
        bool IsTeamScores500Disadvantage(uint32 team) const { return m_TeamScores500Disadvantage[GetTeamIndexByTeamId(team)]; }

    private:

        void PostUpdateImpl(uint32 diff);

        /* Gameobject spawning / despawning. */
        void _CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay);
        void _DelBanner(uint8 node, uint8 type, uint8 teamIndex);
        void _SendNodeUpdate(uint8 node);

        /* Creature spawning / despawning. */
        // TODO: Working, scripted peons spawning.
        void _NodeOccupied(uint8 node, Team team);
        void _NodeDeOccupied(uint8 node);

        int32 _GetNodeNameId(uint8 node);

        /* Nodes info:
            0: neutral
            1: ally contested
            2: horde contested
            3: ally occupied
            4: horde occupied     */

        uint8               m_Nodes[BG_AB_DYNAMIC_NODES_COUNT];
        uint8               m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT];

        BG_AB_BannerTimer   m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT];
        uint32              m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT];

        uint32              m_lastTick[BG_TEAMS_COUNT];
        uint32              m_HonorScoreTics[BG_TEAMS_COUNT];
        uint32              m_ReputationScoreTics[BG_TEAMS_COUNT];

        uint32              m_HonorTics;
        uint32              m_ReputationTics;
        int32               m_CheatersCheckTimer;
        bool                m_IsInformedNearVictory;
        bool                m_TeamScores500Disadvantage[BG_TEAMS_COUNT];        // Needed for achievements.
};

#endif
